package com.ggs.rg.ybjb.adminmodule.util;



import com.ggs.rg.ybjb.adminmodule.service.GoodsService;
import com.ggs.rg.ybjb.adminmodule.service.MaterService;
import com.ggs.rg.ybjb.adminmodule.service.impl.GoodsServiceImpl;
import com.ggs.rg.ybjb.pojomodule.pojo.Goods;
import com.ggs.rg.ybjb.pojomodule.pojo.Mater;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.joda.time.DateTime;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ClassUtils;

import javax.swing.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Date;



/**
 * ClassName:HtmlParseUtil
 * Package:com.ggs.rg.util
 * Description:
 * 爬取数据工具类，读取excel,写入excel案例
 *
 * @Date:2021/8/9 20:28
 * @Author:cxw
 */
public class HtmlParseUtil {

    public static GoodsService goodsService = SpringUtil.getBean(GoodsServiceImpl.class);

    public static MaterService materService = SpringUtil.getBean(MaterService.class);

    /**
     * 利用POI读取爬到的数据,并存入数据库中
     */
    public static void readExcel() throws IOException {
        //创建一个输入流
        FileInputStream fileInputStream = new FileInputStream("D:\\京东商品数据.xls");
        //将输入传入工作薄中，得到工作薄对象
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        //获取工作表
        Sheet sheet = workbook.getSheetAt(1);
        //获取标题行
        Row row = sheet.getRow(0);
        //获取行中总共有多少列row.getPhysicalNumberOfCells()
        int cellNum = row.getPhysicalNumberOfCells();
        System.out.println("excel表中总共有:" + cellNum + "列");
        Cell titleCell01 = row.getCell(0);
        Cell titleCell02 = row.getCell(1);
        Cell titleCell03 = row.getCell(2);
        Cell titleCell04 = row.getCell(3);
        //标题都是String,所以value类型这里不需要判断,直接获取
        System.out.println(titleCell01.getStringCellValue() + "                                 "
                + titleCell02.getStringCellValue() + "         "
                + titleCell03.getStringCellValue() + "         "
                + titleCell04.getStringCellValue());
        //获取总行数
        int rowNum = sheet.getPhysicalNumberOfRows();
        System.out.println("excel表总行数:" + rowNum);

        System.out.println("========================================================================");

        //通过excel读取爬到的电影数据
        for (int i = 1; i < rowNum; i++) {
            Row dataRow = sheet.getRow(i);
            Cell dataCell01 = dataRow.getCell(0);
            Object desc = null,img = null,price = null,infoText = null;
            if (dataCell01 != null) {
                desc = getValue(dataCell01);//调用工具类方法，判断值的类型,获取值
            }
            Cell dataCell02 = dataRow.getCell(1);
            if (dataCell02 != null) {
                img = "http:" + getValue(dataCell02);//调用工具类方法，判断值的类型,获取值
            }
            Cell dataCell03 = dataRow.getCell(2);
            if (dataCell03 != null) {
                price = getValue(dataCell03);//调用工具类方法，判断值的类型,获取值
            }
            Cell dataCell04 = dataRow.getCell(3);
            if (dataCell04 != null) {
                infoText = getValue(dataCell04);//调用工具类方法，判断值的类型,获取值
            }
            String s = (String)price;
            String priceS = s.substring(1);
            String image = (String) img;
            String[] split = image.split("/");
            Goods goods = new Goods("女士秋装",(String)desc,split[split.length-1],0,"服饰");
            goodsService.save(goods);
            String ss = ImageUtil.image2Base64(image);
            ImageUtil.base64ToImage(ClassUtils.getDefaultClassLoader().getResource("static/image").getPath()+"/"+split[split.length-1],ss);
            Mater mater = new Mater((String) infoText,Double.parseDouble(priceS),100,goods.getGid());
            materService.save(mater);
        }
    }

    /**
     * 工具类，判断excel表中行中value类型并获取value,返回
     *
     * @param cell excel中的列对象
     * @return Object对象，因为没执行方法前不知道具体值为啥，所以返回一个object
     * 执行方法过程中，会确认列中数据的类型，并通过对应方法获取对应类型的值，并付给value对象，返回
     */
    public static Object getValue(Cell cell) {
        Object value = null;
        if (cell != null) {
            CellType cellTypeEnum = cell.getCellTypeEnum();
            switch (cellTypeEnum) {
                case ERROR:
//                    System.out.println("没有该数据类型");
                    break;
                case BLANK:
//                    System.out.println("数据类型为空");
                    break;
                case STRING:
//                    System.out.println("数据类型为字符串");
                    value = cell.getStringCellValue();
                    break;
                case BOOLEAN:
//                    System.out.println("数据类型为布尔类型");
                    value = cell.getBooleanCellValue();
                    break;
                case NUMERIC://其他数据类型
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
//                        System.out.println("日期类型");
                        Date date = cell.getDateCellValue();//获取日期格式的数据
                        //引用pom依赖中的joda-time格式化日期，比原生的方便
                        value = new DateTime(date).toString("yyyy-MM-dd HH:mm:ss");//将日期格式化，并赋给返回值
                        //相当于下面两句
//                      SimpleDateFormat parse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//日期格式化
//                      value = parse.format(date);
                        break;
                    } else {
                        //统一设置为String类型
                        cell.setCellType(CellType.STRING);
                        value = cell.getStringCellValue();
//                        System.out.println("将其他数据类型,已被转换成String");
                        break;
                    }
                case FORMULA:
                    String formula = cell.getCellFormula();
//                    System.out.println("公式：" + formula);
                    break;
                default:
//                    System.out.println("该位置没有数据");
                    break;
            }
        }
        return value;
    }

    /**
     * 使用jsoup爬取京东商城的商品，再利用POI将数据批量写入到excel中
     *
     * @return
     * @throws IOException
     */
    public static void jingdongGoods(String keywords) throws IOException {
//        List<Goods> lists = new ArrayList<Goods>();
        //创建一个excel文件
        HSSFWorkbook hssfWorkbook = new HSSFWorkbook();//创建一个工作蒲，就是整个excel\
        HSSFSheet sheet = hssfWorkbook.createSheet();//创建一个工作表，就是excel下面的一个个表
        HSSFRow row = sheet.createRow(0);
        HSSFCell cell01 = row.createCell(0);
        cell01.setCellValue("商品描述");
        HSSFCell cell02 = row.createCell(1);
        cell02.setCellValue("商品图片");
        HSSFCell cell03 = row.createCell(2);
        cell03.setCellValue("商品价格");
        HSSFCell cell04 = row.createCell(3);
        cell04.setCellValue("商品参数");
        Integer count = 0;//用来标记这是第几次录入
        //爬取数据
        for (int i = 1; i <= 1; i++) {
            String url = "https://search.jd.com/Search?keyword=" + keywords + "&page=" + i + "&enc=utf-8";
            //解析网页(jsoup返回Document就是浏览器的Document对象)
            Document document = Jsoup.parse(new URL(url), 300000000);
            //所有你在js中可以使用的方法，这里都能用
            Element element = document.getElementById("J_goodsList");
//        System.out.println(element.html());
            if (element == null) return;
            Elements elements = element.getElementsByTag("li");
            //获取元素中的内容，这里el就是每个li标签了
            for (int j = 0; j < elements.size(); j++) {
                String img = elements.get(j).getElementsByTag("img").eq(0).attr("data-lazy-img");//获取图片
                String price = elements.get(j).getElementsByClass("p-price").eq(0).text();//获取价格
                String title = elements.get(j).getElementsByClass("p-name").eq(0).text();//获取商品标题，描述
                String press = elements.get(j).getElementsByClass("p-shopnum").eq(0).text();//获取出版社
                //按规律创建行和列,count*elements.size()多次录入同一个excel，避免行覆盖掉已被创建的行列数据
                //其实还有bug:elements.size()为每次爬取到的数据数
                //如果:第一次爬取了30条，第二次爬取了29条，那么按这种算法，第二次数据录入的第一条创建的是第30行
                //但第30行已被第一次录入的第30条数据创建，就会造成覆盖
                //解决方法:用一个变量保存上一次的爬取条数，但是我没有做了，要做可以自己做
                HSSFRow dataRow = sheet.createRow((count * elements.size()) + j + 1);
                HSSFCell dataCell01 = dataRow.createCell(0);
                dataCell01.setCellValue(title);
                HSSFCell dataCell02 = dataRow.createCell(1);
                dataCell02.setCellValue(img);
                HSSFCell dataCell03 = dataRow.createCell(2);
                dataCell03.setCellValue(price);
                HSSFCell dataCell04 = dataRow.createCell(3);
                dataCell04.setCellValue(press);
            }
            count++;//次数加1
            //将爬取到的数据写入excel，创建输出流，参数为要保存的文件全路径名
            FileOutputStream fileOutputStream = new FileOutputStream("D:\\京东商品数据.xls",true);
            //写入
            hssfWorkbook.write(fileOutputStream);
            System.out.println("第" + count + "次数据录入完毕");
        }
        System.out.println("商城数据excel表格生成成功!!!");
    }

}



